class PromiseV4 {

    static PENDING = 'pending'
    static FULFILLED = 'fulfilled'
    static REJECTED = 'rejected'

    constructor(executor) {
        // 传递的参数或者reject的理由
        this.value = null
        this.status = PromiseV4.PENDING
        // then 后面异步处理保存
        this.callbacks = []
        try {
            executor(this.resolve.bind(this), this.reject.bind(this))
        } catch (e) {
            this.reject(e)
        }

    }

    resolve(value) {
        this.value = value
        this.status = PromiseV4.FULFILLED
        this.callbacks.map(callback => {
            callback.onfulfilled(value)
        })
    }

    reject(reason) {
        this.value = reason
        this.status = PromiseV4.REJECTED
        this.callbacks.map(callback => {
            callback.onrejected(reason)
        })
    }

    then(onFulfilled, onRejected) {
        if (this.status === PromiseV4.FULFILLED) {
            try {
                onFulfilled(this.value)
            } catch (e) {
                onRejected(e)
            }

        }
        if (this.status === PromiseV4.REJECTED) {
            try {
                onRejected(this.value)
            } catch (e) {
                onRejected(e)
            }
        }
        if (this.status === PromiseV4.PENDING) {
            this.callbacks.push({
                onFulfilled: (value) => {
                    this.resolve(value)
                }, onRejected: (reason) => {
                    this.reject(reason)
                }
            })
        }
    }

    static resolve(value) {
        return PromiseV4((resolve, reject) => {
            if (value instanceof PromiseV4) {
                value.then(resolve, reject)
            } else {
                resolve(value)
            }
        })
    }

    static reject(reason) {
        return new PromiseV4(((resolve, reject) => {
            if (reason instanceof PromiseV4) {
                reason.then(resolve, reject)
            } else {
                reject(reason)
            }
        }))
    }

    static all(values) {
        const res = []
        return new PromiseV4((resolve, reject) => {
            values.map(item => {
                item.then(resolv => {
                    res.push(item)
                    if (res.length === values.length) {
                        resolve(res)
                    }
                }, reason => {
                    reject(reason)
                })
            })
        })
    }

    static race(values) {
        return new PromiseV4((resolve, reject) => {
            values.map(item => {
                item.then(data => {
                    resolve(data)
                }, reason => {
                    reject(reason)
                })
            })
        })
    }
}
